use std::error::Error;
use std::fmt;
use std::fs;
use std::str::FromStr;

fn parse_data() -> (Vec<i32>, usize, usize) {
    let contents = fs::read_to_string("input.txt").unwrap();

    let mut matrix = Vec::new();

    let mut width = 0;
    let mut height = 0;
    for line in contents.trim().lines() {
        height += 1;
        width = line.len();
        for c in line.chars() {
            matrix.push((c == '#') as i32);
        }
    }

    return (matrix, width, height);
}

fn print_matrix(matrix: &Vec<i32>, width: usize, height: usize) {
    for i in 0..height {
        println!("{:?}", &matrix[i * width..i * width + width]);
    }
}

fn calculate_encountered_trees(
    matrix: &Vec<i32>,
    width: usize,
    height: usize,
    slope_x: usize,
    slope_y: usize,
) -> i32 {
    let mut encountered_trees = 0;
    let (mut x, mut y) = (0, 0);
    while (y < height) {
        let x_mod = x % width;

        encountered_trees += matrix[y * width + x_mod];

        x += slope_x;
        y += slope_y;
    }

    return encountered_trees;
}

fn part1() {
    let (matrix, width, height) = parse_data();
    //println!("{:?}, matrix size {}, width {}, height {}", &matrix, matrix.len(), width, height);
    //print_matrix(&matrix, width, height);

    let encountered_trees = calculate_encountered_trees(&matrix, width, height, 3, 1);

    println!("Part 1:");
    println!("encountered trees: {}", encountered_trees);
}

fn part2() {
    println!("Part 2:");
    let (matrix, width, height) = parse_data();
    let slopes = [(1, 1), (3, 1), (5, 1), (7, 1), (1, 2)];
    let mut prod = 1;
    for (slope_x, slope_y) in slopes {
        let encountered_trees =
            calculate_encountered_trees(&matrix, width, height, slope_x, slope_y);
        println!(
            "slope_x {}, slope_y {}, encountered {}",
            slope_x, slope_y, encountered_trees
        );
        prod *= encountered_trees;
    }
    println!("Product: {}", prod);
}

fn main() {
    part1();
    part2();
}
